/**
 * XYF2120 训狗器数码屏驱动
 * Copyright (c) 2021 深圳市智辰科技有限公司
 * All rights reserved.
 */

#include <string.h>

#include "nonos.h"
#include "xyf2120.h"


void xyf2120_init(driver_xyf2120_t* dev) {
	if(!dev) { return; }
	// 默认使能
	dev->enable = true;
	// 清除显示
	xyf2120_clear(dev);
	// 显示默认值
	xyf2120_set(dev, 88, XYF2120_SM_ON, XYF2120_SM_ON, XYF2120_SM_ON, XYF2120_SM_ON, XYF2120_SM_ON, XYF2120_BAT_FULL, XYF2120_RF_FULL);
}

void xyf2120_clear(driver_xyf2120_t* dev) {
	if(!dev) { return; }
	memset(dev->ram.bytes, 0, sizeof(dev->ram.bytes));
}

void xyf2120_display(driver_xyf2120_t* dev, xyf2120_ram_t *ram) {
	memcpy(dev->ram.bytes, ram->bytes, sizeof(dev->ram.bytes));
}

void xyf2120_set(driver_xyf2120_t* dev,
	uint8_t level,
	xyf2120_seg_mode_t levelMode,
	xyf2120_seg_mode_t shakeMode,
	xyf2120_seg_mode_t staticMode,
	xyf2120_seg_mode_t voiceMode,
	xyf2120_seg_mode_t barkMode,
	xyf2120_bat_state_t batState,
	xyf2120_rf_state_t rfState
) {
	if(!dev) { return; }
	xyf2120_clear(dev);
	xyf2120_ram_set_static_level(&dev->ram, level, levelMode);
	xyf2120_ram_set_shake(&dev->ram, shakeMode);
	xyf2120_ram_set_static(&dev->ram, staticMode);
	xyf2120_ram_set_voice(&dev->ram, voiceMode);
	xyf2120_ram_set_bark(&dev->ram, barkMode);
	xyf2120_ram_set_bat_state(&dev->ram, batState);
	xyf2120_ram_set_rf_state(&dev->ram, rfState);
}

void xyf2120_ram_clear(xyf2120_ram_t *ram) {
	memset(ram->bytes, 0, sizeof(ram->bytes));
}

void xyf2120_ram_set_char1(xyf2120_ram_t *ram, xyf2120_8seg_char_t ch, xyf2120_seg_mode_t mode) {
	switch(ch) {
		case XYF2120_8SEG_CHAR_0:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_1:         ram->st.N1A =    0; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E =    0; ram->st.N1F =    0; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_2:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C =    0; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_3:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E =    0; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_4:         ram->st.N1A =    0; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E =    0; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_5:         ram->st.N1A = mode; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E =    0; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_6:         ram->st.N1A = mode; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_7:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E =    0; ram->st.N1F =    0; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_8:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_9:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E =    0; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_A:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_b:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_C:         ram->st.N1A = mode; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_c:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_d:         ram->st.N1A =    0; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_E:         ram->st.N1A = mode; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_F:         ram->st.N1A = mode; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D =    0; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_G:         ram->st.N1A = mode; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_H:         ram->st.N1A =    0; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_h:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_J:         ram->st.N1A =    0; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E =    0; ram->st.N1F =    0; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_L:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_n:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E = mode; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_o:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_p:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C =    0; ram->st.N1D =    0; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_q:         ram->st.N1A = mode; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D =    0; ram->st.N1E =    0; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_r:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D =    0; ram->st.N1E = mode; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_t:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_U:         ram->st.N1A =    0; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F = mode; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_u:         ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E = mode; ram->st.N1F =    0; ram->st.N1G =    0; break;
		case XYF2120_8SEG_CHAR_y:         ram->st.N1A =    0; ram->st.N1B = mode; ram->st.N1C = mode; ram->st.N1D = mode; ram->st.N1E =    0; ram->st.N1F = mode; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_MINUS:     ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D =    0; ram->st.N1E =    0; ram->st.N1F =    0; ram->st.N1G = mode; break;
		case XYF2120_8SEG_CHAR_UNDERLINE: ram->st.N1A =    0; ram->st.N1B =    0; ram->st.N1C =    0; ram->st.N1D = mode; ram->st.N1E =    0; ram->st.N1F =    0; ram->st.N1G =    0; break;
		default: break;
	}
}

void xyf2120_ram_set_char2(xyf2120_ram_t *ram, xyf2120_8seg_char_t ch, xyf2120_seg_mode_t mode) {
	switch(ch) {
		case XYF2120_8SEG_CHAR_0:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_1:         ram->st.N2A =    0; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E =    0; ram->st.N2F =    0; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_2:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C =    0; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_3:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E =    0; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_4:         ram->st.N2A =    0; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E =    0; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_5:         ram->st.N2A = mode; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E =    0; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_6:         ram->st.N2A = mode; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_7:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E =    0; ram->st.N2F =    0; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_8:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_9:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E =    0; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_A:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_b:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_C:         ram->st.N2A = mode; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_c:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_d:         ram->st.N2A =    0; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_E:         ram->st.N2A = mode; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_F:         ram->st.N2A = mode; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D =    0; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_G:         ram->st.N2A = mode; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_H:         ram->st.N2A =    0; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_h:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_J:         ram->st.N2A =    0; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E =    0; ram->st.N2F =    0; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_L:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_n:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E = mode; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_o:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_p:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C =    0; ram->st.N2D =    0; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_q:         ram->st.N2A = mode; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D =    0; ram->st.N2E =    0; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_r:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D =    0; ram->st.N2E = mode; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_t:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_U:         ram->st.N2A =    0; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F = mode; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_u:         ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E = mode; ram->st.N2F =    0; ram->st.N2G =    0; break;
		case XYF2120_8SEG_CHAR_y:         ram->st.N2A =    0; ram->st.N2B = mode; ram->st.N2C = mode; ram->st.N2D = mode; ram->st.N2E =    0; ram->st.N2F = mode; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_MINUS:     ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D =    0; ram->st.N2E =    0; ram->st.N2F =    0; ram->st.N2G = mode; break;
		case XYF2120_8SEG_CHAR_UNDERLINE: ram->st.N2A =    0; ram->st.N2B =    0; ram->st.N2C =    0; ram->st.N2D = mode; ram->st.N2E =    0; ram->st.N2F =    0; ram->st.N2G =    0; break;
		default: break;
	}
}

void xyf2120_ram_set_static_level(xyf2120_ram_t *ram, uint8_t level, xyf2120_seg_mode_t mode) {
	xyf2120_8seg_char_t n1 = (xyf2120_8seg_char_t)(level / 10 + 1), n2 = (xyf2120_8seg_char_t)(level % 10 + 1);
	xyf2120_ram_set_char1(ram, n1, mode);
	xyf2120_ram_set_char2(ram, n2, mode);
}

void xyf2120_ram_set_shake(xyf2120_ram_t *ram, xyf2120_seg_mode_t mode) {
	ram->st.SHAKE = mode;
}

void xyf2120_ram_set_static(xyf2120_ram_t *ram, xyf2120_seg_mode_t mode) {
	ram->st.STATIC = mode;
}

void xyf2120_ram_set_voice(xyf2120_ram_t *ram, xyf2120_seg_mode_t mode) {
	ram->st.VOICE = mode;
}

void xyf2120_ram_set_bark(xyf2120_ram_t *ram, xyf2120_seg_mode_t mode) {
	ram->st.BARK = mode;
}

void xyf2120_ram_set_bat_state(xyf2120_ram_t *ram, xyf2120_bat_state_t state) {
	switch(state) {
		// 电量耗尽: 红灯慢闪
		case XYF2120_BAT_EMPTY:	 ram->st.BAT_OK = 0; ram->st.BAT_WARN = XYF2120_SM_FLASH_SLOW; ram->st.BAT_LOW = 0; ram->st.BAT_MED = 0; ram->st.BAT_HIGH = 0; break;
		// 低电量告警: 红灯常亮，电量1格慢闪
		case XYF2120_BAT_LOW:	 ram->st.BAT_OK = 0; ram->st.BAT_WARN = 1; ram->st.BAT_LOW = XYF2120_SM_FLASH_SLOW; ram->st.BAT_MED = 0; ram->st.BAT_HIGH = 0; break;
		// 电量中等: 白灯常亮，电量2格
		case XYF2120_BAT_MEDIUM: ram->st.BAT_OK = 1; ram->st.BAT_WARN = 0; ram->st.BAT_LOW = 1; ram->st.BAT_MED = 1; ram->st.BAT_HIGH = 0; break;
		// 电量满: 白灯常亮，电量3格
		case XYF2120_BAT_FULL:   ram->st.BAT_OK = 1; ram->st.BAT_WARN = 0; ram->st.BAT_LOW = 1; ram->st.BAT_MED = 1; ram->st.BAT_HIGH = 1; break;
		// 屏幕测试: 红灯慢闪，白灯常亮，电量3格
		case XYF2120_BAT_TEST:   ram->st.BAT_OK = 1; ram->st.BAT_WARN = XYF2120_SM_FLASH_SLOW; ram->st.BAT_LOW = 1; ram->st.BAT_MED = 1; ram->st.BAT_HIGH = 1; break;
		default: break;
	}
}

void xyf2120_ram_set_rf_state(xyf2120_ram_t *ram, xyf2120_rf_state_t state) {
	switch(state) {
		// 无信号: 红灯慢闪
		case XYF2120_RF_LOSS:	ram->st.RF_OK = 0; ram->st.RF_WARN = XYF2120_SM_FLASH_SLOW; ram->st.RF_LOW = 0; ram->st.RF_MED = 0; ram->st.RF_HIGH = 0; break;
		// 信号弱告警: 红灯常亮，信号1格慢闪
		case XYF2120_RF_LOW:	ram->st.RF_OK = 0; ram->st.RF_WARN = 1; ram->st.RF_LOW = XYF2120_SM_FLASH_SLOW; ram->st.RF_MED = 0; ram->st.RF_HIGH = 0; break;
		// 信号中等: 白灯常亮，信号2格
		case XYF2120_RF_MEDIUM: ram->st.RF_OK = 1; ram->st.RF_WARN = 0; ram->st.RF_LOW = 1; ram->st.RF_MED = 1; ram->st.RF_HIGH = 0; break;
		// 信号满格: 白灯常亮，信号3格
		case XYF2120_RF_FULL:   ram->st.RF_OK = 1; ram->st.RF_WARN = 0; ram->st.RF_LOW = 1; ram->st.RF_MED = 1; ram->st.RF_HIGH = 1; break;
		// 屏幕测试: 红灯慢闪，白灯常亮，信号3格
		case XYF2120_RF_TEST:   ram->st.RF_OK = 1; ram->st.RF_WARN = XYF2120_SM_FLASH_SLOW; ram->st.RF_LOW = 1; ram->st.RF_MED = 1; ram->st.RF_HIGH = 1; break;
		default: break;
	}
}

void xyf2120_enable(driver_xyf2120_t* dev, uint8_t enable) {
	if(!dev) { return; }
	dev->enable = enable;
	
	// 如果禁用，则关闭所有 COM/SEG 开关
	if(!dev->enable) { 
		for(int i=0; i<XYF2120_COM_COUNT; i++) { dev->coms[i](0); }
		for(int i=0; i<XYF2120_SEG_COUNT; i++) { dev->segs[i](0); }
		return; 
	}
	
	dev->flashTimeStampSlow = osGetMs();
	dev->flashTimeStampFast = osGetMs();
	dev->flashStateSlow = 1;
	dev->flashStateFast = 1;
	dev->ccom = 0;
}

_RAMCODE_ void _xyf2120_timing_refresh(driver_xyf2120_t* dev) {
	if(!dev->enable) { return; }
	// 关闭当前 COM 端
	dev->coms[dev->ccom](0);
	
	// 取下一个 COM 端对应的 SEG 配置
	dev->ccom = (dev->ccom + 1) % XYF2120_COM_COUNT;
	uint16_t bits = getLeU16(dev->ram.bytes + dev->ccom * 2);
	
	xyf2120_seg_mode_t mode = XYF2120_SM_OFF;
	FUNC_GPIO_Switch pinsw = NULL;
	
	// 设置各个 SEG 状态
	for(int i=0; i<XYF2120_SEG_COUNT; i++) {
		pinsw = dev->segs[i];
		mode = (xyf2120_seg_mode_t)((bits >> (i*2)) & 0x0003);
		
		if(mode == XYF2120_SM_ON) {
			// 常亮
			pinsw(1);
		} else if(mode == XYF2120_SM_FLASH_SLOW) {
			// 慢闪
			if(osElapsedMs(dev->flashTimeStampSlow) >= dev->flashIntervalSlow) {
				// 间隔时间到了，反转并重新计时
				dev->flashStateSlow = !dev->flashStateSlow;
				dev->flashTimeStampSlow = osGetMs();
			}
			pinsw(dev->flashStateSlow);
		} else if(mode == XYF2120_SM_FLASH_FAST) {
			// 快闪
			if(osElapsedMs(dev->flashTimeStampFast) >= dev->flashIntervalFast) {
				// 间隔时间到了，反转并重新计时
				dev->flashStateFast = !dev->flashStateFast;
				dev->flashTimeStampFast = osGetMs();
			}
			pinsw(dev->flashStateFast);
		} else {
			// 关闭
			pinsw(0);
		}
	}
	
	// 打开当前 COM 端
	dev->coms[dev->ccom](1);
}


#define tdelay() mcu_delay_ms(1)

void xyf2120_test(driver_xyf2120_t* dev) {
	// 显示
	xyf2120_set(dev, 88, XYF2120_SM_FLASH_FAST, XYF2120_SM_ON, XYF2120_SM_ON, XYF2120_SM_ON, XYF2120_SM_ON, XYF2120_BAT_TEST, XYF2120_RF_TEST);

	xyf2120_enable(dev, true);
	while(1) {
		_xyf2120_timing_refresh(dev);
		tdelay();
	}
}
